import java.awt.BorderLayout;
import java.awt.Desktop;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;

import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.KeyStroke;
import javax.swing.ListSelectionModel;
import javax.swing.RowFilter;
import javax.swing.border.BevelBorder;
import javax.swing.border.Border;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableRowSorter;

import jxl.Workbook;
import jxl.write.Label;
import jxl.write.WritableSheet;
import jxl.write.WritableWorkbook;
import jxl.write.WriteException;

import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.annotations.XStreamAlias;
import com.thoughtworks.xstream.io.xml.StaxDriver;


public class MainFrame extends JFrame {
	
	private final int FRAME_WIDTH = 1000;
	private final int FRAME_HEIGHT = 800;
	
	private JButton play, settings, scan, export, btnSearch;
	private JTable table;
	@XStreamAlias("film-collection")
	public static Collection filmz;
	private JPanel statusPanel;
	private DefaultTableModel listModel;
	private JTextField searchField;
	private JPanel mainPanel, searchPanel, btnPanel;
	private TableRowSorter<DefaultTableModel> sorter;
	private JLabel numFilms;
	public static JLabel statusLabel;
	private JMenuBar menuBar;
	private JMenu menu;
	private JMenuItem settingsItem;
	private JFrame settingsFrame;
	
	public MainFrame()
	{
		filmz = new Collection();
		settingsFrame = new SettingsFrame();
		settingsFrame.setTitle("Settings");
		settingsFrame.setDefaultCloseOperation(JFrame.HIDE_ON_CLOSE);
		settingsFrame.setResizable(false);
		
		createTable();
		createButtons();
		createTextFields();
		createLabels();
		createMenu();
		createPanel();//called last
		setSize(FRAME_WIDTH, FRAME_HEIGHT);

	}
	
	private void createMenu()
	{
		menuBar = new JMenuBar();
		menu = new JMenu("Options");
		menu.setMnemonic(KeyEvent.VK_A);
		menu.getAccessibleContext().setAccessibleDescription("The place to change things");
		menuBar.add(menu);
		settingsItem = new JMenuItem("Settings...");
		settingsItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_1, ActionEvent.ALT_MASK));
		settingsItem.getAccessibleContext().setAccessibleDescription("Open the settings");
		menu.add(settingsItem);
		settingsItem.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				//show settings frame
				settingsFrame.setVisible(true);
			}
		});
	}
	
	private void createLabels()
	{
		Border loweredbevel = BorderFactory.createLoweredBevelBorder();
		Border raisedbevel = BorderFactory.createRaisedBevelBorder();
		Border compound = BorderFactory.createCompoundBorder(raisedbevel, loweredbevel);
		numFilms = new JLabel("Number of films: " + filmz.getSize());
		numFilms.setHorizontalAlignment(JLabel.CENTER);
		
		statusLabel = new JLabel("testing");
		numFilms.setBorder(compound);
	}
	
	private void createTextFields()
	{
		searchField = new JTextField();
		searchField.setPreferredSize(new Dimension(200, 25));
		searchField.setToolTipText("Clear this field to reset the filter.");
		class SearchListener implements ActionListener
		{
			public void actionPerformed(ActionEvent e)
			{
				String text = searchField.getText();
				if(text.length() == 0)
				{
					sorter.setRowFilter(null);
				}
				else
				{
					sorter.setRowFilter(RowFilter.regexFilter("(?i)" + text));
				}
			}
		}
		
		ActionListener sf = new SearchListener();
		searchField.addActionListener(sf);
		
	}
	private void createButtons()
	{
		scan = new JButton("Rescan");
		settings = new JButton ("Settings");
		play = new JButton("Play Movie");
		btnSearch = new JButton("Filter");
		btnSearch.setPreferredSize(new Dimension(100, 25));
		export = new JButton("Export Library");
		scan.setToolTipText("Rescans your library in the designated folders.");
		settings.setToolTipText("Show settings.");
		play.setToolTipText("Plays the file with your default media player.");
		btnSearch.setToolTipText("Search for items in the list.");
		export.setToolTipText("Exports the library to a spreadsheet. It is saved where the program is being run from.");
		
		class ExportListener implements ActionListener
		{
			public void actionPerformed(ActionEvent e)
			{
				if(filmz.isFilePathSet())
				{
					try {
						WritableWorkbook workbook = Workbook.createWorkbook(new File(filmz.getExportPath() + "movie-manager-library.xls"));
						WritableSheet sheet = workbook.createSheet("First Sheet", 0);
						Label label;
						for(int i = 0; i < filmz.getSize(); i++)
						{
							label = new Label(0, i, filmz.getElementAt(i));
							sheet.addCell(label); 
							label = new Label(1, i, filmz.getLocationAt(i));
							sheet.addCell(label); 
						}
						
						workbook.write(); 
						workbook.close();
						} 
					 catch (IOException | WriteException e1) {
						e1.printStackTrace();
					}
				}
				else
				{
					statusLabel.setText("Can't export a blank Library!");
				}
			}
		}
		class SearchListener implements ActionListener
		{
			public void actionPerformed(ActionEvent e)
			{
				String text = searchField.getText();
				if(text.length() == 0)
				{
					sorter.setRowFilter(null);
				}
				else
				{
					sorter.setRowFilter(RowFilter.regexFilter("(?i)" + text));
				}
			}
		}
		class ListMoviesListener implements ActionListener
		{
			@Override
			public void actionPerformed(ActionEvent e) 
			{
				filmz.buildCollection();
				if(filmz.isFilePathSet() && filmz.getSize() > 0)
				{
					fillTable();
				}
			}
		}
		class SettingsListener implements ActionListener
		{
			public void actionPerformed(ActionEvent e)
			{
				settingsFrame.setVisible(true);
			}
		}
		class PlayActionListener implements ActionListener
		{
			public void actionPerformed(ActionEvent e)
			{
				if(filmz.isFilePathSet())
				{
					int row = table.getSelectedRow();
					String loc = filmz.getLocationAt(table.convertRowIndexToModel(row));
					try {
						Desktop.getDesktop().open(new File(loc));
					} catch (IOException e1) {
						e1.printStackTrace();
					}
				}
			}
		}
		
		ActionListener ex = new ExportListener();
		ActionListener btnS = new SearchListener();
		ActionListener btnPlay = new PlayActionListener();
		ActionListener set = new SettingsListener();
		ActionListener listMovies = new ListMoviesListener();
		scan.addActionListener(listMovies);
		settings.addActionListener(set);
		play.addActionListener(btnPlay);
		btnSearch.addActionListener(btnS);
		export.addActionListener(ex);
		btnSearch.setEnabled(false);
	}
	
	private void createTable()
	{
		listModel = new DefaultTableModel() {

		    @Override
		    public boolean isCellEditable(int row, int column) {
		    	return (column == 2);
		    }
	        @Override
	        public Class<?> getColumnClass(int columnIndex) {
	            if (columnIndex == 2) {
	            	return getValueAt(0, 2).getClass();
	            }
	            return super.getColumnClass(columnIndex);
	        }
//	        @Override
//	        public void setValueAt(Object aValue, int row, int column)
//	        {
//	        	boolean w = filmz.isWatched(table.convertRowIndexToModel(row));
//	        	if (w)
//	        	{
//	        		filmz.setWatched(false, table.convertRowIndexToModel(row));
//	        	}
//	        	else
//	        	{
//	        		filmz.setWatched(false, table.convertRowIndexToModel(row));
//	        	}
//	        }
		};
		table = new JTable(listModel);
		sorter = new TableRowSorter<DefaultTableModel>(listModel);
		table.setRowSorter(null);
		
		listModel.addColumn("File Name");
		listModel.addColumn("Location");
		listModel.addColumn("Watched");
		if(filmz.getSize() > 0)
		{
			fillTable();
		}
	}
	private void createPanel()
	{
		btnPanel = new JPanel(new GridLayout(1, 3));
		mainPanel = new JPanel(new BorderLayout());
		searchPanel = new JPanel(new FlowLayout());
		statusPanel = new JPanel();
		statusPanel.setBorder(new BevelBorder(BevelBorder.LOWERED));
		JScrollPane listScroller = new JScrollPane(table);
		
		statusPanel.add(statusLabel);		
		
		btnPanel.add(scan);
		btnPanel.add(settings);
		btnPanel.add(play);
		btnPanel.add(export);
		btnPanel.add(numFilms);
		
		searchPanel.add(btnSearch);
		searchPanel.add(searchField);
		
		mainPanel.add(listScroller, BorderLayout.CENTER);
		mainPanel.add(btnPanel, BorderLayout.PAGE_END);
		mainPanel.add(searchPanel, BorderLayout.PAGE_START);
		
		add(menuBar, BorderLayout.PAGE_START);
		add(mainPanel, BorderLayout.CENTER);
		add(statusPanel, BorderLayout.PAGE_END);
	}
	private void fillTable()
	{
		filmz.buildCollection();
		listModel.setRowCount(0);
		if(filmz.isFilePathSet())
		{
			for(int i = 0; i < filmz.getSize(); i++)
			{
				listModel.addRow(new Object[]{filmz.getElementAt(i), filmz.getLocationAt(i), filmz.isWatched(i)});
			}
		}
		btnSearch.setEnabled(true);
		numFilms.setText("Number of Films: " + filmz.getSize());
		sorter.modelStructureChanged();
		table.setRowSorter(sorter);
		table.setSelectionMode(ListSelectionModel.SINGLE_INTERVAL_SELECTION);
		table.setAutoResizeMode(JTable.AUTO_RESIZE_ALL_COLUMNS);
	}

}
